package city.spring.modules.material.service.impl;

import city.spring.modules.material.entity.MaterialQuantityEntity;
import city.spring.modules.material.entity.MaterialwarehousingEntity;
import city.spring.modules.material.entity.MaterialwarehousingMaterialExtEntity;
import city.spring.modules.material.entity.StorehouseEntity;
import city.spring.modules.material.repository.MaterialwarehousingMaterialExtRepository;
import city.spring.modules.material.repository.MaterialwarehousingRepository;
import city.spring.modules.material.service.MaterialQuantityService;
import city.spring.modules.material.service.MaterialwarehousingService;
import city.spring.modules.material.service.StorehouseService;
import city.spring.modules.material.vo.MaterialwarehousingMaterialVO;
import city.spring.modules.material.vo.MaterialwarehousingVO;
import city.spring.modules.material.vo.PrintWarehousingVO;
import city.spring.modules.personnel.entity.EmployeeEntity;
import city.spring.modules.personnel.service.EmployeeService;
import city.spring.modules.system.entity.UserEntity;
import city.spring.modules.system.service.UserService;
import city.spring.utils.UserUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Service：入库信息
 *
 * @author 谢金婷
 * @date 2020-04-08 12:05:00
 */
@CacheConfig(cacheNames = {MaterialwarehousingServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Throwable.class)
@Service
public class MaterialwarehousingServiceImpl extends ServiceImpl<MaterialwarehousingRepository, MaterialwarehousingEntity> implements MaterialwarehousingService {
    private static final Logger logger = LoggerFactory.getLogger(MaterialwarehousingServiceImpl.class);

    private final MaterialwarehousingRepository warehousingRepository;
    private final MaterialwarehousingMaterialExtRepository warehousingMaterialExtRepository;
    private final UserService userService;
    private final MaterialQuantityService materialQuantityService;
    private final StorehouseService storehouseService;
    private final EmployeeService employeeService;

    public MaterialwarehousingServiceImpl(MaterialwarehousingRepository warehousingRepository, MaterialwarehousingMaterialExtRepository warehousingMaterialExtRepository, UserService userService, MaterialQuantityService materialQuantityService, StorehouseService storehouseService, EmployeeService employeeService) {
        this.warehousingRepository = warehousingRepository;
        this.warehousingMaterialExtRepository = warehousingMaterialExtRepository;
        this.userService = userService;
        this.materialQuantityService = materialQuantityService;
        this.storehouseService = storehouseService;
        this.employeeService = employeeService;
    }

    @Override
    public void saveWarehousing(MaterialwarehousingEntity entity, @NonNull Principal user) {
        /**
         * 入库信息
         */
        //设置登记人为的当前用户
        UserEntity userEntity = userService.getUserByIdOrAccount(user.getName());
//        entity.setUserId(userEntity.getId());
        entity.setRegistrant(userEntity.getId());
        entity.setCancellation("已入库");
        entity.setIsCan("可以");

        if (!save(entity)) {
            throw new RuntimeException("保存信息失败");
        }

    }

    @Override
    public void updateWarehousing(MaterialwarehousingEntity entity) {
        // 使用 updateById(entity); 修改数据时，将会修改 entity 对象中所有非null数据，如果某个字段为null，将会忽略该字段的修改

        boolean update = updateById(entity);
        if (!update) {
            throw new RuntimeException("修改信息失败");
        }
    }

    @Override
    public void deleteWarehousing(String primaryKey) {
        removeById(primaryKey);
        List<MaterialwarehousingMaterialExtEntity> materialwarehousingShelfs = warehousingMaterialExtRepository.getByWarehousingId(primaryKey);
        if (!materialwarehousingShelfs.isEmpty()) {
            List<String> materialwarehousingShelfId = materialwarehousingShelfs.stream().map(MaterialwarehousingMaterialExtEntity::getId).collect(Collectors.toList());
            warehousingMaterialExtRepository.deleteBatchIds(materialwarehousingShelfId);
        }
    }

    @Override
    public void deleteWarehousing(List<String> primaryKeys) {
        removeByIds(primaryKeys);
    }

    @Override
    public MaterialwarehousingEntity getById(String id) {
        return warehousingRepository.getById(id);
    }

    @Override
    public MaterialwarehousingVO getMaterialWarehousingById(String id) {
        MaterialwarehousingEntity warehousingEntity = warehousingRepository.getById(id);
        System.out.println("warehousingEntity" + warehousingEntity);
        MaterialwarehousingVO warehousingVO = new MaterialwarehousingVO(warehousingEntity);

        // 加载物资列表
        warehousingVO.setMaterials(warehousingMaterialExtRepository.getWarehousingMaterials(id));

        return warehousingVO;
    }

    @Override
    public IPage<MaterialwarehousingVO> listPage(Page<? extends MaterialwarehousingEntity> page, Wrapper<? extends MaterialwarehousingEntity> wrapper) {
        return baseMapper.listPage(page, wrapper);
    }

    /**
     * 入库单作废
     * @param id
     * @param entity
     */
    @Override
    public void checkCancellation(String id, MaterialwarehousingEntity entity) {
        if (entity.getCancellation().equals("已作废")) {
//            JOptionPane.showMessageDialog(null, "该入库单已作废，无需操作", "错误", JOptionPane.ERROR_MESSAGE);
            throw new RuntimeException("该入库单已作废，无需操作");
        } else {
            if (entity.getIsCan().equals("可以")) {
                entity.setCancellation("已作废");
                // 该入库单下的入库物资信息
                List<MaterialwarehousingMaterialVO> warehousingMaterials = warehousingMaterialExtRepository.getWarehousingMaterials(id);
                for (MaterialwarehousingMaterialVO materialVO : warehousingMaterials) {
                    // 根据入库单id，物资id，仓库id确定入库物资
                    MaterialwarehousingMaterialExtEntity materialExtEntity = warehousingMaterialExtRepository.getByMaterialwarehousingIdAndMaterialIdAndStorehouseId(materialVO.getMaterialwarehousingId(), materialVO.getMaterialId(), materialVO.getStorehouseId());
                    materialExtEntity.setCancellation("已作废");
                    warehousingMaterialExtRepository.updateById(materialExtEntity);

                    // 根据物资id，仓库id在MaterialQuantityEntity确定物资
                    MaterialQuantityEntity materialQuantityEntity = materialQuantityService.getByMaterialIdAndStorehouseId(materialExtEntity.getMaterialId(), materialExtEntity.getStorehouseId());
                    // 入库入住作废后更新库存表的入库数量，平均单价，库存数量,总价
                    BigDecimal warehousingquantity = materialQuantityEntity.getWarehousingquantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getWarehousingquantity();
                    BigDecimal quantity = materialQuantityEntity.getQuantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getQuantity();
                    BigDecimal total = materialQuantityEntity.getTotal() == null ? BigDecimal.ZERO : materialQuantityEntity.getTotal();
                    materialQuantityEntity.setWarehousingquantity(warehousingquantity.subtract(materialExtEntity.getWarehousingquantity()));
                    materialQuantityEntity.setQuantity(quantity.subtract(materialExtEntity.getWarehousingquantity()));
                    materialQuantityEntity.setTotal(total.subtract(materialExtEntity.getTotal()));

                    BigDecimal quantity1 = materialQuantityEntity.getQuantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getQuantity();
                    BigDecimal total1 = materialQuantityEntity.getTotal() == null ? BigDecimal.ZERO : materialQuantityEntity.getTotal();

                    if (quantity1.compareTo(BigDecimal.ZERO) != 0 || total1.compareTo(BigDecimal.ZERO) != 0) {
                        System.out.println(quantity1.compareTo(BigDecimal.ZERO) != 0);
                        System.out.println(total1.compareTo(BigDecimal.ZERO) != 0);
                        assert materialQuantityEntity.getTotal() != null;
                        materialQuantityEntity.setUnitprice(total1.divide(quantity1, 2));
                    } else {
                        materialQuantityEntity.setUnitprice(BigDecimal.ZERO);
                    }
                    materialQuantityService.lambdaUpdate()
                            .set(MaterialQuantityEntity::getWarehousingquantity, materialQuantityEntity.getWarehousingquantity())
                            .set(MaterialQuantityEntity::getQuantity, materialQuantityEntity.getQuantity())
                            .set(MaterialQuantityEntity::getTotal, materialQuantityEntity.getTotal())
                            .set(MaterialQuantityEntity::getUnitprice, materialQuantityEntity.getUnitprice())
                            .eq(MaterialQuantityEntity::getId, materialQuantityEntity.getId())
                            .update();
                }
                warehousingRepository.checkCancellation(id, entity);
            } else if (entity.getIsCan().equals("不可以")) {
//                JOptionPane.showMessageDialog(null, "该入库单已有物资出库，不允许作废", "错误", JOptionPane.ERROR_MESSAGE);
                throw new RuntimeException("该入库单已有物资出库，不允许作废");
            }
        }
    }

    @Override
    public PrintWarehousingVO getPrintWarehousing(List<String> ids) {
        List<MaterialwarehousingEntity> list;
        if (ids.isEmpty()) {
            list = new ArrayList<>();
        } else {
            list = lambdaQuery().in(MaterialwarehousingEntity::getId, ids).list();
        }
        Set<String> collect = list.stream().map(MaterialwarehousingEntity::getId).collect(Collectors.toSet());
        if (collect.size() != 1) {
            throw new RuntimeException("请只选择一个入库单");
        }
        PrintWarehousingVO vo = new PrintWarehousingVO();
        vo.setPreparer(UserUtils.getUser().getNickname());
        // 生成打印时所需要的打印明细
        List<PrintWarehousingVO.PrintWarehousingRecordVO> recordVOList = list.stream().map(item -> {
            StorehouseEntity storehouseEntity = storehouseService.getById(item.getStorehouseId());
            EmployeeEntity employeeEntity = employeeService.getById(item.getUserId());
            PrintWarehousingVO.PrintWarehousingRecordVO recordVO = new PrintWarehousingVO.PrintWarehousingRecordVO();
            recordVO.setId(item.getId());
            recordVO.setStorehouseId(item.getStorehouseId());
            recordVO.setSname(storehouseEntity.getSname());
            recordVO.setWarehousingdate(item.getWarehousingdate());
            recordVO.setWarehouseId(item.getWarehouseId());
            recordVO.setMaterialSource(item.getMaterialSource());
            recordVO.setUserId(item.getUserId());
            recordVO.setName(employeeEntity.getName());
            recordVO.setRemark(item.getRemark());
            recordVO.setCancellation(item.getCancellation());
            return recordVO;
        }).collect(Collectors.toList());
        vo.setList(recordVOList);
        return vo;
    }
}